/*
 * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 *
 * This file is part of Harmattan SmashMiner OpenGL game application.
 * 
 * Harmattan SmashMiner OpenGL Example Application version 1.0.0
 *  
 * Latest update: 15.4.2011
 *
 * The Harmattan SmashMiner OpenGL example application demonstrates how to use 
 * the OpenGL ES in Harmattan devices.
 *
 * This example is provided as a starting point for 3rd party
 * developers (you) to ease the implementation of OpenGL based 
 * games. Ideas, parts of code or methodologies that this
 * example application uses can be freely used without restrictions.
 *
 * See file README.txt how to build and compile this example application
 * in the Harmattan SDK environment. 
 * 
 * See file INSTALL.txt to find out what is required to run this
 * application and how to install the application to the device or
 * alternatively in QEMU-emulator.
 *
 * The LICENSE.txt file explains the license this software is provided
 * with. A copy of the same license is included in this source file.
 * 
 */

/*
 * Copyright (C) 2011 by Nokia Corporation.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/*! 
 * \class   GameLevel
 * \brief   Provides game data for each level and scales the game data according to difficulty
 * settings.
 */
#include "gamelevel.h"
#include "gameengine.h"

#include <QDebug>

/*!
 * Constructor of GameLevel class.
 *
 * \param difficulty    Difficulty level from settings (1 = easy, 2 = normal, 3 = hard)
 * \param parent        Parent object
 */
GameLevel::GameLevel(int difficulty, QObject *parent) 
    : QObject(parent)
    , levelNumber(0)
{
    scaleDifficulty(difficulty);
}


/*! Initializes the game data for next game level.
 *
 * Array \c GameEngine::currentLevelProgress contains the current level progress value in index 0 and the
 * maximum progress value in index 1. Progress points are counted as follows:
 *  
 *  - splitting a large asteroid: +1 progress point.
 *  - splitting three medium asteroids: +1x3 progress point.
 *  - collecting the resulting minerals: +4x3 progress point.
 *
 *  There are +16 progress points in each large asteroid. The maximum progress for level is \f$16 * a\f$, 
 *  where \f$a\f$ is amount of large asteroids for the level.
 *
 *  \code
 *  \endcode
 *
 * \param copy          The structure to store the level data 
 * \param progressData  The maximum progress will be calculated to index 1 and current progress will be reset to 0. 
 */
void GameLevel::nextLevel(GameLevelData &copy, int *progressData)
{
    if (++levelNumber > MaxLevel)
        newRound();

    createData();

    // copy the data and apply the difficulty level settings.

    copy.maxObjectsInScreen = data.maxObjectsInScreen;

    copy.asteroids = data.asteroids;
    copy.asteroidSpeedLarge = data.asteroidSpeedLarge * difficulty;
    copy.asteroidSpeedMedium = data.asteroidSpeedMedium * difficulty;

    copy.ufos = data.ufos;
    copy.missileSpeed = data.missileSpeed * difficulty;
    copy.missileIncidence = (data.missileIncidence * data.missileIncidence / 10.0f) * difficulty;
    copy.missileGuidance = data.missileGuidance * difficulty;

    copy.meteorShowers = data.meteorShowers;
    copy.meteorShowerSize = data.meteorShowerSize;
    copy.meteorShowerSpeed = data.meteorShowerSpeed;
    copy.meteorShowerRadiusChange = data.meteorShowerRadiusChange;

    copy.blackholes = data.blackholes;
    copy.blackholeSpeed = data.blackholeSpeed;
    copy.blackholeRadius = data.blackholeRadius;

    copy.comets = data.comets;
    copy.cometSpeed = data.cometSpeed;
    copy.cometLengthChange = data.cometLengthChange;
    copy.cometWidth = data.cometWidth;
    copy.cometWidthChange = data.cometWidthChange;

    copy.bombs = data.bombs;
    copy.hyperjumps = data.hyperjumps;

    // add randomly bombs to levels for which
    // there is a setting of zero bombs...

    if (!copy.bombs) {
        if (GameEngine::getRandomF() < 0.333f)
            copy.bombs++;
    }

#ifdef SMASHMINER_CONFIG_ENABLE_DEBUG_CHECKS

    if (copy.maxObjectsInScreen < PotentialObjectsLargeAsteroid)
        qFatal("GameLevel::nextLevel() : maxObjectsInScreen = %d "
                "the value is too small -> cannot launch large asteroids to screen.", 
                copy.maxObjectsInScreen);

#endif  // SMASHMINER_CONFIG_ENABLE_DEBUG_CHECKS

    // count the maximum progress value.
    // splitting a large asteroid = +1 progress point.
    // splitting three medium asteroids = +1x3 progress point.
    // collecting the resulting minerals = +4x3 progress point.

    // -> there are +16 progress points in each large asteroid.

    progressData[0] = 0;
    progressData[1] = copy.asteroids * 16;
}

/*! Initializes a new round with increased difficulty.
 */
void GameLevel::newRound()
{
    difficulty += 0.2;
    levelNumber = 1;
}

/*! Provides game data for each level.
 */
void GameLevel::createData()
{
    switch (levelNumber) {
    case 1:
        data.maxObjectsInScreen = PotentialObjectsLargeAsteroid * 2 - 6;// allow one large asteroid

        data.asteroids = 1;
        data.asteroidSpeedLarge = 6.0f;
        data.asteroidSpeedMedium = 9.0f;

        data.ufos = 1;
        data.missileSpeed = 0.0f;
        data.missileIncidence = 0.0f;
        data.missileGuidance = 0.0f;

        data.meteorShowers = 0;
        data.meteorShowerSize = 0;
        data.meteorShowerSpeed = 0.0f;
        data.meteorShowerRadiusChange = 0.0f;

        data.blackholes = 0;
        data.blackholeSpeed = 2.0f;
        data.blackholeRadius = 0.0f;

        data.comets = 0;
        data.cometSpeed = 0.0f;
        data.cometLengthChange = 0.0f;
        data.cometWidth = 0.0f;
        data.cometWidthChange = 0.0f;

        data.bombs = 0;
        data.hyperjumps = 1;

        break;
    case 2:
        data.maxObjectsInScreen = PotentialObjectsLargeAsteroid * 2 + 6; // allow 2 asteroids

        data.asteroids = 2;
        data.asteroidSpeedLarge = 6.0f;
        data.asteroidSpeedMedium = 9.0f;

        data.ufos = 1;
        data.missileSpeed = 12.0f;// max-value is 30.0
        data.missileIncidence = 0.15f;
        data.missileGuidance = 0.00f;

        data.meteorShowers = 0;
        data.meteorShowerSize = 0;
        data.meteorShowerSpeed = 0.0f;
        data.meteorShowerRadiusChange = 0.0f;

        data.blackholes = 0;
        data.blackholeSpeed = 3.0f;
        data.blackholeRadius = 0.0f;

        data.comets = 0;
        data.cometSpeed = 0.0f;
        data.cometLengthChange = 0.0f;
        data.cometWidth = 0.0f;
        data.cometWidthChange = 0.0f;

        data.bombs = 0;
        data.hyperjumps = 2;

        break;
    case 3:
        data.maxObjectsInScreen = PotentialObjectsLargeAsteroid * 2 + 6;

        data.asteroids = 3;
        data.asteroidSpeedLarge = 7.0f;
        data.asteroidSpeedMedium = 10.0f;

        data.ufos = 1;
        data.missileSpeed = 13.0f;// max-value is 30.0
        data.missileIncidence = 0.15f;
        data.missileGuidance = 0.025f;

        data.meteorShowers = 0;
        data.meteorShowerSize = 0;
        data.meteorShowerSpeed = 0.0f;
        data.meteorShowerRadiusChange = 0.0f;

        data.blackholes = 1;
        data.blackholeSpeed = 3.0f;
        data.blackholeRadius = 15.0f;//min-value is 15.0 for efficient swallowing effect!

        data.comets = 0;
        data.cometSpeed = 0.0f;
        data.cometLengthChange = 0.0f;
        data.cometWidth = 0.0f;
        data.cometWidthChange = 0.0f;

        data.bombs = 0;
        data.hyperjumps = 2;

        break;
    case 4:
        data.maxObjectsInScreen = PotentialObjectsLargeAsteroid * 2 + 6;

        data.asteroids = 4;
        data.asteroidSpeedLarge = 7.0f;
        data.asteroidSpeedMedium = 10.0f;

        data.ufos = 1;
        data.missileSpeed = 14.0f;// max-value is 30.0
        data.missileIncidence = 0.16f;
        data.missileGuidance = 0.050f;

        data.meteorShowers = 0;
        data.meteorShowerSize = 0;
        data.meteorShowerSpeed = 0.0f;
        data.meteorShowerRadiusChange = 0.0f;

        data.blackholes = 1;
        data.blackholeSpeed = 3.0f;
        data.blackholeRadius = 15.0f;//min-value is 15.0 for efficient swallowing effect!

        data.comets = 0;
        data.cometSpeed = 0.0f;
        data.cometLengthChange = 0.0f;
        data.cometWidth = 0.0f;
        data.cometWidthChange = 0.0f;

        data.bombs = 0;
        data.hyperjumps = 3;

        break;
    case 5:
        data.maxObjectsInScreen = PotentialObjectsLargeAsteroid * 2 + 6;

        data.asteroids = 5;
        data.asteroidSpeedLarge = 8.0f;
        data.asteroidSpeedMedium = 11.0f;

        data.ufos = 1;
        data.missileSpeed = 15.0f;// max-value is 30.0
        data.missileIncidence = 0.16f;
        data.missileGuidance = 0.075f;

        data.meteorShowers = 0;
        data.meteorShowerSize = 0;
        data.meteorShowerSpeed = 0.0f;
        data.meteorShowerRadiusChange = 0.0f;

        data.blackholes = 1;
        data.blackholeSpeed = 3.0f;
        data.blackholeRadius = 16.0f;//min-value is 15.0 for efficient swallowing effect!

        data.comets = 0;
        data.cometSpeed = 0.0f;
        data.cometLengthChange = 0.0f;
        data.cometWidth = 0.0f;
        data.cometWidthChange = 0.0f;

        data.bombs = 0;
        data.hyperjumps = 3;

        break;
    case 6:
        data.maxObjectsInScreen = PotentialObjectsLargeAsteroid * 2 + 6;

        data.asteroids = 6;
        data.asteroidSpeedLarge = 8.0f;
        data.asteroidSpeedMedium = 11.0f;

        data.ufos = 2;
        data.missileSpeed = 16.0f;// max-value is 30.0
        data.missileIncidence = 0.17f;
        data.missileGuidance = 0.100f;

        data.meteorShowers = 0;
        data.meteorShowerSize = 0;
        data.meteorShowerSpeed = 0.0f;
        data.meteorShowerRadiusChange = 0.0f;

        data.blackholes = 1;
        data.blackholeSpeed = 4.0f;
        data.blackholeRadius = 16.0f;//min-value is 15.0 for efficient swallowing effect!

        data.comets = 1;
        data.cometSpeed = 6.0f;
        data.cometLengthChange = 6.0f;//max-value is 20.0
        data.cometWidth = 1.0f;
        data.cometWidthChange = data.cometLengthChange * 0.5f;

        data.bombs = 1;// starting from here it is no longer possible to clear a level by just launching a bomb.
        data.hyperjumps = 3;

        break;
    case 7:
        data.maxObjectsInScreen = PotentialObjectsLargeAsteroid * 2 + 6;

        data.asteroids = 7;
        data.asteroidSpeedLarge = 9.0f;
        data.asteroidSpeedMedium = 12.0f;

        data.ufos = 2;
        data.missileSpeed = 17.0f;// max-value is 30.0
        data.missileIncidence = 0.17f;
        data.missileGuidance = 0.125f;

        data.meteorShowers = 0;
        data.meteorShowerSize = 0;
        data.meteorShowerSpeed = 0.0f;
        data.meteorShowerRadiusChange = 0.0f;

        data.blackholes = 1;
        data.blackholeSpeed = 4.0f;
        data.blackholeRadius = 18.0f;//min-value is 15.0 for efficient swallowing effect!

        data.comets = 1;
        data.cometSpeed = 6.0f;
        data.cometLengthChange = 7.0f;//max-value is 20.0
        data.cometWidth = 2.0f;
        data.cometWidthChange = data.cometLengthChange * 0.5f;

        data.bombs = 0;
        data.hyperjumps = 4;

        break;
    case 8:
        data.maxObjectsInScreen = PotentialObjectsLargeAsteroid * 2 + 6;

        data.asteroids = 8;
        data.asteroidSpeedLarge = 9.0f;
        data.asteroidSpeedMedium = 12.0f;

        data.ufos = 2;
        data.missileSpeed = 18.0f;// max-value is 30.0
        data.missileIncidence = 0.18f;
        data.missileGuidance = 0.150f;

        data.meteorShowers = 1;
        data.meteorShowerSize = 1;
        data.meteorShowerSpeed = 3.0f;
        data.meteorShowerRadiusChange = 0.5f;// max-value is 1.0 to prevent gaps from arriving!

        data.blackholes = 1;
        data.blackholeSpeed = 4.0f;
        data.blackholeRadius = 18.0f;//min-value is 15.0 for efficient swallowing effect!

        data.comets = 1;
        data.cometSpeed = 7.0f;
        data.cometLengthChange = 8.0f;//max-value is 20.0
        data.cometWidth = 3.0f;
        data.cometWidthChange = data.cometLengthChange * 0.5f;

        data.bombs = 1;
        data.hyperjumps = 4;

        break;
    case 9:
        data.maxObjectsInScreen = PotentialObjectsLargeAsteroid * 2 + 6;

        data.asteroids = 9;
        data.asteroidSpeedLarge = 10.0f;
        data.asteroidSpeedMedium = 13.0f;

        data.ufos = 2;
        data.missileSpeed = 19.0f;// max-value is 30.0
        data.missileIncidence = 0.18f;
        data.missileGuidance = 0.175f;

        data.meteorShowers = 1;
        data.meteorShowerSize = 1;
        data.meteorShowerSpeed = 3.0f;
        data.meteorShowerRadiusChange = 0.5f;// max-value is 1.0 to prevent gaps from arriving!

        data.blackholes = 1;
        data.blackholeSpeed = 5.0f;
        data.blackholeRadius = 20.0f;//min-value is 15.0 for efficient swallowing effect!

        data.comets = 1;
        data.cometSpeed = 7.0f;
        data.cometLengthChange = 9.0f;//max-value is 20.0
        data.cometWidth = 4.0f;
        data.cometWidthChange = data.cometLengthChange * 0.5f;

        data.bombs = 0;
        data.hyperjumps = 4;

        break;
    case 10:
        data.maxObjectsInScreen = PotentialObjectsLargeAsteroid * 2 + 6;

        data.asteroids = 10;
        data.asteroidSpeedLarge = 10.0f;
        data.asteroidSpeedMedium = 13.0f;

        data.ufos = 3;
        data.missileSpeed = 20.0f;// max-value is 30.0
        data.missileIncidence = 0.19f;
        data.missileGuidance = 0.200f;

        data.meteorShowers = 1;
        data.meteorShowerSize = 1;
        data.meteorShowerSpeed = 4.0f;
        data.meteorShowerRadiusChange = 0.5f;// max-value is 1.0 to prevent gaps from arriving!

        data.blackholes = 1;
        data.blackholeSpeed = 5.0f;
        data.blackholeRadius = 20.0f;//min-value is 15.0 for efficient swallowing effect!

        data.comets = 1;
        data.cometSpeed = 8.0f;
        data.cometLengthChange = 10.0f;//max-value is 20.0
        data.cometWidth = 5.0f;
        data.cometWidthChange = data.cometLengthChange * 0.5f;

        data.bombs = 1;// here it would take 3 bombs to clear the level -> start adding bombs contantly.
        data.hyperjumps = 4;

        break;
    case 11:
        data.maxObjectsInScreen = PotentialObjectsLargeAsteroid * 2 + 6;

        data.asteroids = 11;
        data.asteroidSpeedLarge = 11.0f;
        data.asteroidSpeedMedium = 14.0f;

        data.ufos = 3;
        data.missileSpeed = 21.0f;// max-value is 30.0
        data.missileIncidence = 0.19f;
        data.missileGuidance = 0.225f;

        data.meteorShowers = 1;
        data.meteorShowerSize = 2;
        data.meteorShowerSpeed = 4.0f;
        data.meteorShowerRadiusChange = 0.5f;// max-value is 1.0 to prevent gaps from arriving!

        data.blackholes = 1;
        data.blackholeSpeed = 5.0f;
        data.blackholeRadius = 22.0f;//min-value is 15.0 for efficient swallowing effect!

        data.comets = 1;
        data.cometSpeed = 8.0f;
        data.cometLengthChange = 11.0f;//max-value is 20.0
        data.cometWidth = 6.0f;
        data.cometWidthChange = data.cometLengthChange * 0.5f;

        data.bombs = 1;
        data.hyperjumps = 5;

        break;
    case 12:
        data.maxObjectsInScreen = PotentialObjectsLargeAsteroid * 2 + 6;

        data.asteroids = 12;
        data.asteroidSpeedLarge = 11.0f;
        data.asteroidSpeedMedium = 14.0f;

        data.ufos = 3;
        data.missileSpeed = 22.0f;// max-value is 30.0
        data.missileIncidence = 0.20f;
        data.missileGuidance = 0.250f;

        data.meteorShowers = 1;
        data.meteorShowerSize = 2;
        data.meteorShowerSpeed = 5.0f;
        data.meteorShowerRadiusChange = 0.5f;// max-value is 1.0 to prevent gaps from arriving!

        data.blackholes = 2;
        data.blackholeSpeed = 6.0f;
        data.blackholeRadius = 22.0f;//min-value is 15.0 for efficient swallowing effect!

        data.comets = 1;
        data.cometSpeed = 9.0f;
        data.cometLengthChange = 12.0f;//max-value is 20.0
        data.cometWidth = 7.0f;
        data.cometWidthChange = data.cometLengthChange * 0.5f;

        data.bombs = 1;
        data.hyperjumps = 5;

        break;
    case 13:
        data.maxObjectsInScreen = PotentialObjectsLargeAsteroid * 3 + 6;

        data.asteroids = 13;
        data.asteroidSpeedLarge = 12.0f;
        data.asteroidSpeedMedium = 15.0f;

        data.ufos = 3;
        data.missileSpeed = 23.0f;// max-value is 30.0
        data.missileIncidence = 0.20f;
        data.missileGuidance = 0.275f;

        data.meteorShowers = 1;
        data.meteorShowerSize = 3;
        data.meteorShowerSpeed = 5.0f;
        data.meteorShowerRadiusChange = 1.0f;// max-value is 1.0 to prevent gaps from arriving!

        data.blackholes = 1;
        data.blackholeSpeed = 6.0f;
        data.blackholeRadius = 24.0f;//min-value is 15.0 for efficient swallowing effect!

        data.comets = 1;
        data.cometSpeed = 9.0f;
        data.cometLengthChange = 13.0f;//max-value is 20.0
        data.cometWidth = 8.0f;
        data.cometWidthChange = data.cometLengthChange * 0.5f;

        data.bombs = 1;
        data.hyperjumps = 5;

        break;
    case 14:
        data.maxObjectsInScreen = PotentialObjectsLargeAsteroid * 3 + 6;

        data.asteroids = 14;
        data.asteroidSpeedLarge = 12.0f;
        data.asteroidSpeedMedium = 15.0f;

        data.ufos = 4;
        data.missileSpeed = 24.0f;// max-value is 30.0
        data.missileIncidence = 0.21f;
        data.missileGuidance = 0.300f;

        data.meteorShowers = 1;
        data.meteorShowerSize = 3;
        data.meteorShowerSpeed = 6.0f;
        data.meteorShowerRadiusChange = 1.0f;// max-value is 1.0 to prevent gaps from arriving!

        data.blackholes = 1;
        data.blackholeSpeed = 6.0f;
        data.blackholeRadius = 24.0f;//min-value is 15.0 for efficient swallowing effect!

        data.comets = 1;
        data.cometSpeed = 10.0f;
        data.cometLengthChange = 14.0f;//max-value is 20.0
        data.cometWidth = 9.0f;
        data.cometWidthChange = data.cometLengthChange * 0.5f;

        data.bombs = 1;
        data.hyperjumps = 5;

        break;
    case 15:
        data.maxObjectsInScreen = PotentialObjectsLargeAsteroid * 3 + 6;

        data.asteroids = 15;
        data.asteroidSpeedLarge = 13.0f;
        data.asteroidSpeedMedium = 16.0f;

        data.ufos = 4;
        data.missileSpeed = 25.0f;// max-value is 30.0
        data.missileIncidence = 0.21f;
        data.missileGuidance = 0.325f;

        data.meteorShowers = 1;
        data.meteorShowerSize = 4;
        data.meteorShowerSpeed = 6.0f;
        data.meteorShowerRadiusChange = 1.0f;// max-value is 1.0 to prevent gaps from arriving!

        data.blackholes = 1;
        data.blackholeSpeed = 6.0f;
        data.blackholeRadius = 26.0f;//min-value is 15.0 for efficient swallowing effect!

        data.comets = 1;
        data.cometSpeed = 10.0f;
        data.cometLengthChange = 15.0f;//max-value is 20.0
        data.cometWidth = 10.0f;
        data.cometWidthChange = data.cometLengthChange * 0.5f;

        data.bombs = 1;
        data.hyperjumps = 6;

        break;
    case 16:
        data.maxObjectsInScreen = PotentialObjectsLargeAsteroid * 3 + 6;

        data.asteroids = 16;
        data.asteroidSpeedLarge = 13.0f;
        data.asteroidSpeedMedium = 16.0f;

        data.ufos = 4;
        data.missileSpeed = 26.0f;// max-value is 30.0
        data.missileIncidence = 0.22f;
        data.missileGuidance = 0.350f;

        data.meteorShowers = 1;
        data.meteorShowerSize = 5;
        data.meteorShowerSpeed = 7.0f;
        data.meteorShowerRadiusChange = 1.0f;// max-value is 1.0 to prevent gaps from arriving!

        data.blackholes = 1;
        data.blackholeSpeed = 7.0f;
        data.blackholeRadius = 26.0f;//min-value is 15.0 for efficient swallowing effect!

        data.comets = 2;
        data.cometSpeed = 11.0f;
        data.cometLengthChange = 16.0f;//max-value is 20.0
        data.cometWidth = 11.0f;
        data.cometWidthChange = data.cometLengthChange * 0.5f;

        data.bombs = 2;
        data.hyperjumps = 6;

        break;
    case 17:
        data.maxObjectsInScreen = PotentialObjectsLargeAsteroid * 3 + 6;

        data.asteroids = 17;
        data.asteroidSpeedLarge = 14.0f;
        data.asteroidSpeedMedium = 17.0f;

        data.ufos = 4;
        data.missileSpeed = 27.0f;// max-value is 30.0
        data.missileIncidence = 0.22f;
        data.missileGuidance = 0.375f;

        data.meteorShowers = 1;
        data.meteorShowerSize = 6;
        data.meteorShowerSpeed = 7.0f;
        data.meteorShowerRadiusChange = 1.0f;// max-value is 1.0 to prevent gaps from arriving!

        data.blackholes = 2;
        data.blackholeSpeed = 7.0f;
        data.blackholeRadius = 28.0f;//min-value is 15.0 for efficient swallowing effect!

        data.comets = 2;
        data.cometSpeed = 11.0f;
        data.cometLengthChange = 17.0f;//max-value is 20.0
        data.cometWidth = 12.0f;
        data.cometWidthChange = data.cometLengthChange * 0.5f;

        data.bombs = 1;
        data.hyperjumps = 6;

        break;
    case 18:
        data.maxObjectsInScreen = PotentialObjectsLargeAsteroid * 3 + 6;

        data.asteroids = 18;
        data.asteroidSpeedLarge = 14.0f;
        data.asteroidSpeedMedium = 17.0f;

        data.ufos = 5;
        data.missileSpeed = 28.0f;// max-value is 30.0
        data.missileIncidence = 0.23f;
        data.missileGuidance = 0.400f;

        data.meteorShowers = 1;
        data.meteorShowerSize = 7;
        data.meteorShowerSpeed = 8.0f;
        data.meteorShowerRadiusChange = 1.0f;// max-value is 1.0 to prevent gaps from arriving!

        data.blackholes = 2;
        data.blackholeSpeed = 7.0f;
        data.blackholeRadius = 28.0f;//min-value is 15.0 for efficient swallowing effect!

        data.comets = 2;
        data.cometSpeed = 12.0f;
        data.cometLengthChange = 18.0f;//max-value is 20.0
        data.cometWidth = 13.0f;
        data.cometWidthChange = data.cometLengthChange * 0.5f;

        data.bombs = 2;
        data.hyperjumps = 6;

        break;
    case 19:
        data.maxObjectsInScreen = PotentialObjectsLargeAsteroid * 3 + 6;

        data.asteroids = 19;
        data.asteroidSpeedLarge = 15.0f;
        data.asteroidSpeedMedium = 18.0f;

        data.ufos = 5;
        data.missileSpeed = 29.0f;// max-value is 30.0
        data.missileIncidence = 0.24f;
        data.missileGuidance = 0.425f;

        data.meteorShowers = 2;
        data.meteorShowerSize = 8;
        data.meteorShowerSpeed = 8.0f;
        data.meteorShowerRadiusChange = 1.0f;// max-value is 1.0 to prevent gaps from arriving!

        data.blackholes = 2;
        data.blackholeSpeed = 8.0f;
        data.blackholeRadius = 30.0f;//min-value is 15.0 for efficient swallowing effect!

        data.comets = 2;
        data.cometSpeed = 12.0f;
        data.cometLengthChange = 19.0f;//max-value is 20.0
        data.cometWidth = 14.0f;
        data.cometWidthChange = data.cometLengthChange * 0.5f;

        data.bombs = 1;
        data.hyperjumps = 7;
        break;
    case 20:
        data.maxObjectsInScreen = PotentialObjectsLargeAsteroid * 3 + 6;

        data.asteroids = 20;
        data.asteroidSpeedLarge = 15.0f;
        data.asteroidSpeedMedium = 18.0f;

        data.ufos = 6;
        data.missileSpeed = 30.0f;// max-value is 30.0
        data.missileIncidence = 0.24f;
        data.missileGuidance = 0.450f;

        data.meteorShowers = 2;
        data.meteorShowerSize = 9;
        data.meteorShowerSpeed = 9.0f;
        data.meteorShowerRadiusChange = 1.0f;// max-value is 1.0 to prevent gaps from arriving!

        data.blackholes = 2;
        data.blackholeSpeed = 8.0f;
        data.blackholeRadius = 30.0f;//min-value is 15.0 for efficient swallowing effect!

        data.comets = 2;
        data.cometSpeed = 14.0f;
        data.cometLengthChange = 20.0f;//max-value is 20.0
        data.cometWidth = 15.0f;
        data.cometWidthChange = data.cometLengthChange * 0.5f;

        data.bombs = 2;// here it would take 4 bombs to clear the level.
        data.hyperjumps = 7;
        break;

    default:
        qFatal("GameLevel::createData() : bad level %d", levelNumber);
    }
}

/*! Scales the difficulty from int to float.
 * \param d Difficulty from settings (1 = easy, 2 = normal, 3 = hard).
 */
void GameLevel::scaleDifficulty(int d)
{
    switch(d) {
        case 1:
            difficulty = 0.45f;
            break;
        case 2:
            difficulty = 0.75f;
            break;
        case 3:
            difficulty = 1.0f;
            break;
        default:
            qFatal("GameLevel::scaleDifficulty() : invalid difficulty level %d.", d);
    }
}
